package 哈希表.查找共用字符;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author: wh(1835734390 @ qq.com)
 * @date: 2023/2/27 17:15
 * @description:
 * @version:
 */
public class Solution {
    public static void main(String[] args) {
        String[] str = {"cool","lock","cook"};
        System.out.println(commonChars(str));
    }


    public static List<String> commonChars(String[] words) {
        List<String> list = new ArrayList<>();
        Map<Character,Integer> map = new HashMap<>();
        for (int i = 0; i < words[0].length(); i++) {
            map.put(words[0].charAt(i),map.getOrDefault(words[0].charAt(i),0)+1);
        }
        for (int i = 1; i < words.length; i++) {
            Map<Character,Integer> tmpMap = new HashMap<>();
            for (int j = 0; j < words[i].length(); j++) {
                if (map.containsKey(words[i].charAt(j))){
                    Integer value = map.get(words[i].charAt(j));
                    if (value != 0) {
                        --value;
                        map.put(words[i].charAt(j),value);
                        tmpMap.put(words[i].charAt(j),tmpMap.getOrDefault(words[i].charAt(j),0)+1);
                    }
                }
            }
            map = tmpMap;
        }
        Iterator<Map.Entry<Character, Integer>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Character, Integer> entry = iterator.next();
            Integer value = entry.getValue();
            Character key = entry.getKey();
            for (int i = 0; i < value; i++) {
                list.add(String.valueOf(key));
            }
        }
        return list;
    }


    //和上方法核心思想是一样的，但是比上面的要简便一些，无需采用hash表。
    public static List<String> test(String[] words) {
        String word = words[0];
        List<Character> list = new ArrayList<>();
        for (int i = 0; i < word.length(); i++) {
            list.add(word.charAt(i));
        }

        for (int i = 1; i < words.length; i++) {
            List<Character> tmpList = new ArrayList<>();
            String tmpStr = words[i];
            for (int j = 0; j < tmpStr.length(); j++) {
                char tmpChar = tmpStr.charAt(j);
                if (list.contains(tmpChar)) {
                    list.remove(new Character(tmpChar));
                    tmpList.add(tmpChar);
                }
            }
            list = tmpList;
        }
        return list.stream().map(x -> x.toString()).collect(Collectors.toList());
    }


    public static List<String> commonChars2(String[] A) {
        // 思路：统计每个字符出现次数，有一个单词未出现就置0输出所有单词中出现0次以上】
        // 存放26个字符在单词列表的每个单词中都出现的频率
        int[] minFreq = new int[26];
        // 填充max方便下降比较
        // 降到0就最小，说明该字符在某个单词中未出现，结果中也就不需要输出
        Arrays.fill(minFreq, Integer.MAX_VALUE);
        // 遍历统计
        for (String word : A) {
            // 记录每个单词中各字符出现情况
            int[] freq = new int[26];
            int length = word.length();
            // 遍历单词
            for (int i = 0; i < length; i++) {
                // 统计某单词中字符出现情况
                char ch = word.charAt(i);
                // 累加字符出现次数
                ++freq[ch - 'a'];
            }
            // 统计完每个单词都去更新每个单词的最低出现频率
            for (int i = 0; i < 26; i++) {
                // 更新每个单词中每个字符出现的最少次数
                // 如果某个字符只在单个单词中出现自然这个字符计数会被置为0
                minFreq[i] = Math.min(minFreq[i], freq[i]);
            }
        }
        List<String> ans = new ArrayList<>();
        // 汇总输出结果
        for (int i = 0; i < 26; i++) {
            // 如果某字符只在某个单词中出现或没出现那么频率会被将为0不被计入结果
            // 其他在每个单词中都出现的字符计数多次
            for (int j = 0; j < minFreq[i]; j++) {
                ans.add(String.valueOf((char) (i + 'a')));
            }
        }
        return ans;

    }


    public static Function<Character,String> getFunction() {
        Function<Character,String> function = character -> character.toString();
        return function;
    }
}
